package com.emailsystem.emailsystem.util.Impl;


import com.emailsystem.emailsystem.domain.Email;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.codec.net.QuotedPrintableCodec;

import java.io.*;
import java.net.URLDecoder;
import java.util.*;

public class FileUtilImpl{

    public static final String LINE_SEPARATOR = "\r\n";

    /**
     * 下面三个是自己的邮件系统用来编码解码
     */
    public static String MIME_Message_withoutAttachment(Email email) throws UnsupportedEncodingException {

        //构建消息头部
        StringBuilder headerBuilder = new StringBuilder();
        headerBuilder.append("From: ").append("\"").append(email.getSenderNickname()).append("\"").append(" <").append(email.getSender()).append(">").append(LINE_SEPARATOR);
        headerBuilder.append("To: ").append("\"").append(email.getReceiverNickname()).append("\"").append(" <").append(email.getReceiver()).append(">").append(LINE_SEPARATOR);
        headerBuilder.append("Subject: ").append(email.getSubject()).append(LINE_SEPARATOR);


        // 构造消息体部分
        StringBuilder bodyBuilder = new StringBuilder();
        bodyBuilder.append(email.getContent()).append(LINE_SEPARATOR);

        // 构造纯文本消息
        StringBuilder messageBuilder = new StringBuilder();
        messageBuilder.append("MIME-Version: 1.0").append(LINE_SEPARATOR);
        /*messageBuilder.append("Content-Type: text/plain; boundary=boundary").append(LINE_SEPARATOR);
        messageBuilder.append(LINE_SEPARATOR);
        messageBuilder.append("--boundary").append(LINE_SEPARATOR);*/

        // 添加正文
        messageBuilder.append("Content-Type: text/plain;").append(LINE_SEPARATOR);
        messageBuilder.append("charset=\"utf-8\"").append(LINE_SEPARATOR);
        messageBuilder.append("Content-Transfer-Encoding: base64").append(LINE_SEPARATOR);
        messageBuilder.append(LINE_SEPARATOR);
        messageBuilder.append(Base64.getEncoder().encodeToString(bodyBuilder.toString().getBytes("utf-8"))).append(LINE_SEPARATOR);

        /*// 结束纯文本消息部分
        messageBuilder.append("--boundary--").append(LINE_SEPARATOR);*/

        return headerBuilder.toString() + messageBuilder.toString();
    }

    public static String MIME_Message_withAttachment(Email email) throws IOException {

        //构建消息头部
        StringBuilder headerBuilder = new StringBuilder();
        headerBuilder.append("From: ").append("\"").append(email.getSenderNickname()).append("\"").append(" <").append(email.getSender()).append(">").append(LINE_SEPARATOR);
        headerBuilder.append("To: ").append("\"").append(email.getReceiverNickname()).append("\"").append(" <").append(email.getReceiver()).append(">").append(LINE_SEPARATOR);
        headerBuilder.append("Subject: ").append(email.getSubject()).append(LINE_SEPARATOR);


        // 构造消息体部分
        StringBuilder bodyBuilder = new StringBuilder();
        bodyBuilder.append(email.getContent()).append(LINE_SEPARATOR);


        // 构造multipart/mixed消息
        StringBuilder messageBuilder = new StringBuilder();
        //messageBuilder.append("MIME-Version: 1.0").append(LINE_SEPARATOR);
        messageBuilder.append("Content-Type: multipart/mixed; boundary=boundary00").append(LINE_SEPARATOR);
        messageBuilder.append(LINE_SEPARATOR);
        messageBuilder.append("--boundary00").append(LINE_SEPARATOR);

        // 添加正文
        messageBuilder.append("Content-Type: text/plain; charset=utf-8").append(LINE_SEPARATOR);
        messageBuilder.append("Content-Transfer-Encoding: base64").append(LINE_SEPARATOR);
        messageBuilder.append(LINE_SEPARATOR);
        messageBuilder.append(Base64.getEncoder().encodeToString(bodyBuilder.toString().getBytes("utf-8"))).append(LINE_SEPARATOR);
        messageBuilder.append(LINE_SEPARATOR);


        // 添加附件
        for (File attachment : email.getAttachment()) {

            byte[] attachmentData = getAttachmentData(email.getAttachment().get(0)); // 获取附件二进制数据
            messageBuilder.append("--boundary00").append(LINE_SEPARATOR);
            messageBuilder.append("Content-Type: application/octet-stream").append(LINE_SEPARATOR);
            messageBuilder.append("charset=\"uft-8\";").append(LINE_SEPARATOR);
            messageBuilder.append("name=\"").append(attachment.getName()).append("\"").append(LINE_SEPARATOR);////////////
            messageBuilder.append("Content-Disposition: attachment; filename=" + encodeText(attachment.getName())).append(LINE_SEPARATOR);
            messageBuilder.append("Content-Transfer-Encoding: base64").append(LINE_SEPARATOR);
            messageBuilder.append(LINE_SEPARATOR);
            messageBuilder.append(Base64.getEncoder().encodeToString(attachmentData)).append(LINE_SEPARATOR);

        }


        // 结束multipart/mixed消息部分
        messageBuilder.append("--boundary00--").append(LINE_SEPARATOR);


        return headerBuilder.toString() + messageBuilder.toString();
    }

    public static Email Decode_MIME(String MIME_Message) throws IOException {
        Email email = new Email();

        // 分离邮件头和正文部分
        int headerEndIndex = MIME_Message.indexOf(FileUtilImpl.LINE_SEPARATOR + FileUtilImpl.LINE_SEPARATOR);
        String headerStr = MIME_Message.substring(0, headerEndIndex);
        String bodyStr = MIME_Message.substring(headerEndIndex);//.replace(FileUtilImpl.LINE_SEPARATOR + "--boundary", "--boundary");

        // 解码并处理邮件头部
        Map<String, String> headers = new HashMap<>();
        for (String line : headerStr.split(FileUtilImpl.LINE_SEPARATOR)) {
            String[] kv = line.split(":\\s?", 2); // 将键值对拆开
            if (kv.length == 2) {
                headers.put(kv[0], kv[1]);
            }
        }

        // 解码并处理消息体，从中提取附件和正文内容
        String attachmentFilename = null;
        byte[] attachmentData = null;
        String bodyContent = null;
        String currentPartContentType = null;

        for (String part : bodyStr.split("--boundary")) {
            String[] lines = part.trim().split(FileUtilImpl.LINE_SEPARATOR);

            if (lines.length >= 2 && lines[0].startsWith("Content-Type: ")) {
                currentPartContentType = lines[0].substring("Content-Type: ".length());
                if (lines.length >= 4 && lines[2].contains("attachment")) {
                    attachmentFilename = new String(Base64.getDecoder().decode(lines[2].substring(lines[2].indexOf("filename=") + "filename=".length()))); // 获取附件文件名，并对其解码
                    attachmentData = new byte[0];
                }
            }
            if ("application/octet-stream".equals(currentPartContentType) && attachmentFilename != null) { // 处理附件部分
                String[]partlines = part.split("\r\n");

                byte[] decodedData = Base64.getDecoder().decode(partlines[5].getBytes());//不应该是整个part

                attachmentData = Arrays.copyOf(attachmentData, attachmentData.length + decodedData.length); // 扩展数组
                System.arraycopy(decodedData, 0, attachmentData, attachmentData.length - decodedData.length, decodedData.length); // 复制数据
                currentPartContentType = "";
            }
            if ("text/plain; charset=utf-8".equals(currentPartContentType)) { // 处理正文部分
                String[]partlines = part.split("\r\n");
                bodyContent = new String(Base64.getMimeDecoder().decode(partlines[4].getBytes()));
                currentPartContentType = "";/////////////////////
            }

        }

        email.setSubject(new String(Base64.getDecoder().decode(headers.get("Subject"))));
        email.setSender(headers.get("From"));
        email.setReceiver(headers.get("To"));
        email.setEmailID(headers.get("X-QQ-mid"));
        email.setSendTime(headers.get("Date"));
        email.setContent(bodyContent);

        File attachment = new File(attachmentFilename);
        try (FileOutputStream fos = new FileOutputStream(attachment)) {
            fos.write(attachmentData);
        } catch (IOException e) {
            System.out.println("An error occurred while writing the byte array to file: " + e.getMessage());
        }
        ArrayList<File> a = new ArrayList<>();
        a.add(attachment);
        email.setAttachment(a);


        return email;
    }

    /**
     * 下面是解码QQ邮件的内容
     */
    public static ArrayList<Email> Decode_QQMails(String MIME_Message) throws IOException {
        ArrayList<Email> emails = new ArrayList<>();

        MIME_Message = MIME_Message.trim().replaceFirst("^\\s*\n", "");
        String[] emailss = MIME_Message.split("X-QQ-FEAT:");

        for (String s : emailss) {
            if (!s.isEmpty()){
                Email e = Decode_QQMail(("X-QQ-FEAT: " + s.trim().replaceFirst("^\\s*\n", "")).trim());
                emails.add(e);
            }
        }

        return emails;
    }

    public static ArrayList<Email> DecodeIMAPMAils(String Message) throws IOException {
        ArrayList<Email> emails = new ArrayList<>();

        Message = Message.trim().replaceFirst("^\\s*\n", "");
        String[] emailss = Message.split("BODY\\[HEAD");

        for (int i = 1; i < emailss.length; i++) {
            if (!emailss[i].isEmpty()){
                Email e = DecodeIMAPMail(("BODY[HEAD" + emailss[i].trim().replaceFirst("^\\s*\n", "")).trim());
                emails.add(e);
            }
        }

        return emails;
    }

    public static Email Decode_QQMail(String MIME_Message) throws IOException {
        Email email = new Email();
        MIME_Message = MIME_Message.trim();
        // 分离邮件头和正文部分
        int headerEndIndex = MIME_Message.indexOf(FileUtilImpl.LINE_SEPARATOR + FileUtilImpl.LINE_SEPARATOR);
        String headerStr = MIME_Message.substring(0, headerEndIndex);
        String bodyStr = MIME_Message.substring(headerEndIndex);

        // 解码并处理邮件头部
        Map<String, String> headers = new HashMap<>();
        for (String line : headerStr.split(FileUtilImpl.LINE_SEPARATOR)) {
            String[] kv = line.split(":\\s?", 2); // 将键值对拆开

            if (kv.length == 2) {
                if (kv[1].contains("boundary")){
                    headers.put(kv[0], kv[1].substring(kv[1].indexOf(":") + 1,kv[1].indexOf(";")));
                    headers.put("boundary",kv[1].substring(kv[1].indexOf("=")));
                }else
                    headers.put(kv[0], kv[1].trim());
            }
            if (line.contains("boundary")){
                String[] b = line.trim().replaceAll("\"","").split("=",2);
                headers.put("boundary",b[1]);
            }
            if (line.contains("charset")){
                headers.put("charset",line.substring(line.indexOf("=") + 1).replaceAll("\"","").trim());
            }
        }

        if (isBase64(headers.get("Subject")))
            email.setSubject(decodeText(headers.get("Subject")));
        else
            email.setSubject(headers.get("Subject"));

        String From = headers.get("From");
        if (From.contains("<"))
            email.setSender(From.substring(From.indexOf("<") + 1,From.lastIndexOf(">")));
        else
            email.setSender(From);

        if (From.contains("=")){
            if(isBase64(From.substring(From.indexOf("="),From.lastIndexOf("=") + 1)))
                email.setSenderNickname(FileUtilImpl.decodeText(From.substring(From.indexOf("="),From.lastIndexOf("=") + 1)));
        }else {
            email.setSenderNickname(From);
        }




        String To = headers.get("To");
        if (To.contains("<"))
            email.setReceiver(To.substring(To.indexOf("<") + 1,To.indexOf(">")));
        else
            email.setReceiver(To);

        if (To.contains("=")){
            if(isBase64(To.substring(To.indexOf("="),To.lastIndexOf("=") + 1)))
                email.setReceiverNickname(FileUtilImpl.decodeText(To.substring(To.indexOf("="),To.lastIndexOf("=") + 1)));
        }else {
            email.setReceiverNickname(To);
        }

        email.setEmailID(headers.get("X-QQ-mid"));


        email.setSendTime(headers.get("Date"));

        String boundary = "";
        // 解码并处理消息体，从中提取附件和正文内容
        String attachmentFilename = null;
        byte[] attachmentData = null;
        String bodyContent = "";
        String currentPartContentType = "";
        String currentCodeType = null;
        String currentEncoding = null;
        byte[] htmlData = null;
        ArrayList<File> a = new ArrayList<>();
        email.setAttachment(a);
        StringBuilder attachmentName = new StringBuilder();


        boundary = headers.get("boundary");

        if (headers.get("Content-Type").contains("multipart"))
            for (String part : bodyStr.split(boundary)) {

                String[] lines = part.trim().split(FileUtilImpl.LINE_SEPARATOR);

                if (lines.length >= 2 && lines[0].startsWith("Content-Type: ")) {
                    if (lines[0].contains(";")){
                        currentPartContentType = lines[0].substring("Content-Type: ".length(),lines[0].indexOf(";")).trim();
                    }else{
                        currentPartContentType = lines[0].substring("Content-Type: ".length()).trim();
                    }

                    if (currentPartContentType.contains("multipart")){
                        partingDecode(part,email,headers.get("Message-ID"));
                        continue;
                    }
                    if (lines[0].contains("charset")){
                        if(lines[0].substring(lines[0].indexOf("charset")).contains(";")){
                            currentCodeType = lines[0].substring(lines[0].indexOf("=") + 1 , lines[0].indexOf(";" , lines[0].indexOf("charset"))).replaceAll("\"","").trim();
                        }else {
                            currentCodeType = lines[0].substring(lines[0].indexOf("=") + 1).replaceAll("\"","").trim();
                        }
                        currentEncoding = lines[1].substring(lines[1].indexOf(":") + 1).replaceAll("\"","").trim();
                    } else
                    {
                        if(lines[1].substring(lines[1].indexOf("charset")).contains(";")){
                            currentCodeType = lines[1].substring(lines[1].indexOf("=") + 1 , lines[1].indexOf(";" , lines[1].indexOf("charset"))).replaceAll("\"","").trim();
                        }else {
                            currentCodeType = lines[1].substring(lines[1].indexOf("=") + 1).replaceAll("\"","").trim();
                        }
                        currentEncoding = lines[2].substring(lines[2].indexOf(":") + 1).replaceAll("\"","").trim();
                    }

                    if (lines.length >= 4 && lines[3].contains("attachment")) {
                        if (lines[2].contains(".")){
                            attachmentFilename = lines[2].substring(lines[2].indexOf("\"")+1,lines[2].lastIndexOf("\""));
                        }else {
                            //String tmp = lines[2].substring(lines[2].indexOf("\"")+1,lines[2].lastIndexOf("\"")); // 获取附件文件名，并对其解码
                            attachmentFilename = FileUtilImpl.decodeText(lines[2].substring(lines[2].indexOf("\"")+1,lines[2].lastIndexOf("\""))); // 获取附件文件名，并对其解码
                        }
                        attachmentData = new byte[0];
                    }
                }
                if ("application/octet-stream".equals(currentPartContentType) && attachmentFilename != null) { // 处理附件部分
                    //String[]partlines = part.split("\r\n");

                    StringBuilder sb = new StringBuilder();
                    int index = 0;
                    while (!"".equals(lines[index])){
                        index+=1;
                    }
                    if("".equals(lines[index])){
                        index+=1;
                    }

                    while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                        sb.append(lines[index].trim());
                        index+=1;
                    }

                    byte[] decodedData = Base64.getDecoder().decode(sb.toString().getBytes());//不应该是整个part

                    attachmentData = Arrays.copyOf(attachmentData, attachmentData.length + decodedData.length); // 扩展数组
                    System.arraycopy(decodedData, 0, attachmentData, attachmentData.length - decodedData.length, decodedData.length); // 复制数据
                    currentPartContentType = "";




                    String path = "receiveAttachment\\";
                    if (email.getReceiver().contains("@")){
                        path += email.getReceiver().substring(0,email.getReceiver().indexOf("@"));
                        path += "\\";
                    }else {
                        path += email.getReceiver();
                        path += "\\";
                    }
                    File directory = new File(path);
                    if (!directory.exists()) {
                        directory.mkdirs();
                    }

                    path+=attachmentFilename;
                    File attachment = new File(path);
                    try (FileOutputStream fos = new FileOutputStream(attachment)) {
                        fos.write(attachmentData);
                    } catch (IOException e) {
                        System.out.println("An error occurred while writing the byte array to file: " + e.getMessage());
                    }

                    email.getAttachment().add(attachment);
                    if(attachmentName.length()>0){
                        attachmentName.append("?").append(attachmentFilename);
                    }else{
                        attachmentName.append(attachmentFilename);
                    }
                }
                if ("text/plain".equals(currentPartContentType)) { // 处理正文部分
                    //String[]partlines = part.split("\r\n");
                    StringBuilder sb = new StringBuilder();
                    int index = 0;
                    while (!"".equals(lines[index])){
                        index+=1;
                    }
                    if("".equals(lines[index])){
                        index+=1;
                    }

                    //String line = lines[index];

                    if (currentEncoding.startsWith("b") || currentEncoding.startsWith("B")){

                        while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                            sb.append(lines[index].trim());
                            index+=1;
                        }
                        bodyContent = new String(Base64.getMimeDecoder().decode(sb.toString().getBytes()),currentCodeType);

                    } else if (currentEncoding.startsWith("q") || currentEncoding.startsWith("Q")) {

                        while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                            sb.append(lines[index].trim());
                            index+=1;
                        }
                        QuotedPrintableCodec codec = new QuotedPrintableCodec();
                        try {
                            bodyContent = codec.decode(sb.toString(),currentCodeType);
                        } catch (Exception e) {
                            bodyContent = sb.toString();
                        }

                    } else if (currentEncoding.startsWith("7")) {
                        while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                            sb.append(lines[index].trim()).append("\n");
                            index+=1;
                        }
                        bodyContent = sb.toString();
                    } else if (currentEncoding.startsWith("8")) {
                        while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                            sb.append(lines[index].trim());
                            index+=1;
                        }
                        bodyContent = new String(sb.toString().getBytes(),currentCodeType);
                    }else{
                        while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                            sb.append(lines[index].trim());
                            index+=1;
                        }
                        bodyContent = sb.toString();
                    }


                    email.setContent(bodyContent);
                    currentPartContentType = "";
                }
                if (currentPartContentType.contains("text/html")) { // 处理html部分
                    //String[]partlines = part.split("\r\n");
                    htmlData = new byte[0];
                    StringBuilder sb = new StringBuilder();
                    int index = 0;
                    while (!"".equals(lines[index].trim()))
                        index+=1;

                    if("".equals(lines[index])){
                        index+=1;
                    }
                    byte[] decodedData = null;

                    //以下设置HTML文件


                    if ("base64".equals(currentEncoding)){

                        String line = lines[index];
                        while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                            sb.append(lines[index].trim());
                            index+=1;
                        }
                        decodedData = Base64.getDecoder().decode(sb.toString().getBytes());
                        htmlData = Arrays.copyOf(htmlData, htmlData.length + decodedData.length); // 扩展数组
                        System.arraycopy(decodedData, 0, htmlData, htmlData.length - decodedData.length, decodedData.length); // 复制数据

                        if (email.getContent()==null){
                            email.setContent(sb.toString());
                        }
                        email.setHtmlString(sb.toString());
                    }
                    else if ("QUOTED-PRINTABLE".equals(currentEncoding)||"quoted-printable".equals(currentEncoding)){
                        String line = lines[index];
                        while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                            sb.append(lines[index].trim());
                            index+=1;
                        }
                        if (email.getContent()==null){
                            email.setContent(sb.toString());
                        }
                        email.setHtmlString(sb.toString());
                    }else {
                        String line = lines[index];
                        while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                            sb.append(lines[index].trim()).append("\n");
                            index+=1;
                        }
                        if (email.getContent()==null){
                            email.setContent(sb.toString());
                        }
                    }


                    currentPartContentType = "";
                }

            }
        else if (headers.containsKey("Content-Transfer-Encoding")) {

            if ("base64".equals(headers.get("Content-Transfer-Encoding")) || "Base64".equals(headers.get("Content-Transfer-Encoding"))){
                bodyStr = bodyStr.replaceAll("(\r\n)*|\n*|\r*","");
                bodyContent = new String(Base64.getDecoder().decode(bodyStr.getBytes()), headers.get("charset"));
            }else if ("7bit".equals(headers.get("Content-Transfer-Encoding"))){
                //遇到的7bit 好像都解码好了 所以直接拿
                bodyContent = bodyStr.replaceAll("\r","");
            }else if ("8bit".equals(headers.get("Content-Transfer-Encoding"))){
                bodyStr = bodyStr.replaceAll("\r","");
                bodyContent = new String(bodyStr.getBytes(),headers.get("charset"));
            }else if ("quoted-printable".equals(headers.get("Content-Transfer-Encoding")) || "QUOTED-PRINTABLE".equals(headers.get("Content-Transfer-Encoding"))){
                bodyStr = bodyStr.replaceAll("\r","");
                bodyContent = FileUtilImpl.decodeText(bodyStr);
            }else {
                bodyContent = bodyStr.replaceAll("\r","");
            }

            email.setContent(bodyContent);
        }



        email.setAttachmentName(attachmentName.toString());

        return email;
    }

    public static String getPOP3EmailID(String MIME_Message){
        MIME_Message = MIME_Message.trim();
        // 分离邮件头和正文部分
        int headerEndIndex = MIME_Message.indexOf(FileUtilImpl.LINE_SEPARATOR + FileUtilImpl.LINE_SEPARATOR);
        String headerStr;
        if (headerEndIndex==-1){
            headerStr = MIME_Message;
        } else {
            headerStr = MIME_Message.substring(0, headerEndIndex);
        }

        // 处理邮件头部 获取id
        for (String line : headerStr.split(FileUtilImpl.LINE_SEPARATOR)) {
            if (line.contains("X-QQ-mid")){
                String[] kv = line.split(":\\s?", 2); // 将键值对拆开
                if (kv.length == 2) {
                    return kv[1].trim();
                }
            }
        }
        return "";
    }

    public static String getIMAPEmailID(String Message){
        Message = Message.trim();
        // 分离邮件头和正文部分
        int headerEndIndex = Message.indexOf("FETCH (BODY[TEXT]");
        String headerStr;
        if (headerEndIndex == -1) {
            headerStr = Message;
        }else {
            headerStr = Message.substring(0, headerEndIndex);
        }

        // 处理邮件头部 并获得ID
        for (String line : headerStr.split(FileUtilImpl.LINE_SEPARATOR)) {
            if (line.contains("X-QQ-mid")){
                String[] kv = line.split(":\\s?", 2); // 将键值对拆开
                if (kv.length == 2) {
                    return kv[1].trim();
                }
            }
        }

        return "";
    }

    private static void partingDecode (String bodyStr , Email email , String messageID) throws IOException {
        String boundary = "";

        for (String part : bodyStr.split("\n")) {
            if (part.contains("boundary")){
                boundary = part.substring(part.indexOf("\"") + 1,part.lastIndexOf("\"")).trim();
                break;
            }
        }

        //String attachmentFilename = null;
        byte[] htmlData = null;
        String bodyContent = null;
        String currentPartContentType = null;
        String currentCodeType = null;
        String currentEncoding = null;

        for (String part : bodyStr.split(boundary)) {

            String[] lines = part.trim().split(FileUtilImpl.LINE_SEPARATOR);

            if (lines.length > 2 && lines[0].startsWith("Content-Type: ")) {
                if (lines[0].contains(";")){
                    currentPartContentType = lines[0].substring("Content-Type: ".length(),lines[0].indexOf(";")).trim();
                }else{
                    currentPartContentType = lines[0].substring("Content-Type: ".length()).trim();
                }

                if (lines[0].contains("charset")){
                    currentCodeType = lines[0].substring(lines[0].indexOf("=") + 1).trim();
                    currentEncoding = lines[1].substring(lines[1].indexOf(":") + 1).trim();
                } else if (lines[1].contains("charset"))
                {
                    currentCodeType = lines[1].substring(lines[1].indexOf("\"") + 1,lines[1].lastIndexOf("\""));
                    currentEncoding = lines[2].substring(lines[2].indexOf(":") + 1).trim();
                }
            }
            if ("text/plain".equals(currentPartContentType)) { // 处理正文部分

                StringBuilder sb = new StringBuilder();
                int index = 0;

                while (!"".equals(lines[index]))
                    index+=1;

                if("".equals(lines[index])){
                    index+=1;
                }


                while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                    sb.append(lines[index].trim());
                    index+=1;
                }

                bodyContent = new String(Base64.getMimeDecoder().decode(sb.toString().getBytes()),currentCodeType);
                email.setContent(bodyContent);
                currentPartContentType = "";

            }
            if ("text/html".equals(currentPartContentType)) { // 处理html部分
                //String[]partlines = part.split("\r\n");
                htmlData = new byte[0];
                StringBuilder sb = new StringBuilder();
                int index = 0;
                while (!"".equals(lines[index].trim()))
                    index+=1;

                if("".equals(lines[index])){
                    index+=1;
                }
                byte[] decodedData = null;

                //以下设置HTML文件


                if ("base64".equals(currentEncoding.trim())){
                    while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                        sb.append(lines[index].trim());
                        index+=1;
                    }
                    decodedData = Base64.getDecoder().decode(sb.toString().getBytes());
                    htmlData = Arrays.copyOf(htmlData, htmlData.length + decodedData.length); // 扩展数组
                    System.arraycopy(decodedData, 0, htmlData, htmlData.length - decodedData.length, decodedData.length); // 复制数据



                    if (email.getContent()==null){
                        email.setContent(sb.toString());
                    }
                    email.setHtmlString(sb.toString());
                }else if ("QUOTED-PRINTABLE".equals(currentEncoding)||"quoted-printable".equals(currentEncoding)){


                    while (index<lines.length&&!boundary.equals(lines[index].trim())&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                        sb.append(lines[index].trim());
                        index+=1;
                    }

//                    if (email.getContent()==null){
                    email.setContent(sb.toString());
//                    }

                    email.setHtmlString(URLDecoder.decode(sb.toString(),currentCodeType));
                }
                currentPartContentType = "";
            }

        }

    }

    public static Email DecodeIMAPMail(String Message) throws IOException {
        Email email = new Email();
        Message = Message.trim();
        // 分离邮件头和正文部分
        int headerEndIndex = Message.indexOf("FETCH (BODY[TEXT]");
        if (headerEndIndex == -1)return null;
        String headerStr = Message.substring(0, headerEndIndex);
        String bodyStr = Message.substring(headerEndIndex);

        // 解码并处理邮件头部
        Map<String, String> headers = new HashMap<>();
        for (String line : headerStr.split(FileUtilImpl.LINE_SEPARATOR)) {
            String[] kv = line.split(":\\s?", 2); // 将键值对拆开

            if (kv.length == 2) {
                if (kv[1].contains("boundary")){
                    headers.put(kv[0], kv[1].substring(kv[1].indexOf(":") + 1,kv[1].indexOf(";")));
                    headers.put("boundary",kv[1].substring(kv[1].indexOf("=")).replaceAll("\"","").trim());
                }else
                    headers.put(kv[0], kv[1].trim());
            }
            if (line.contains("boundary")){
                String[] b = line.trim().replaceAll("\"","").split("=",2);
                headers.put("boundary",b[1].replaceAll("\"","").trim());
            }
            if (line.contains("charset")){
                headers.put("charset",line.substring(line.indexOf("=") + 1).replaceAll("\"","").trim());
            }
        }


        if (isBase64(headers.get("Subject")))
            email.setSubject(decodeText(headers.get("Subject")));
        else
            email.setSubject(headers.get("Subject"));

        String From = headers.get("From");
        if (From.contains("<"))
            email.setSender(From.substring(From.indexOf("<") + 1,From.lastIndexOf(">")));
        else
            email.setSender(From);

        if (From.contains("=")){
            if(isBase64(From.substring(From.indexOf("="),From.lastIndexOf("=") + 1)))
                email.setSenderNickname(FileUtilImpl.decodeText(From.substring(From.indexOf("="),From.lastIndexOf("=") + 1)));
        }else {
            email.setSenderNickname(From);
        }




        String To = headers.get("To");
        if (To.contains("<"))
            email.setReceiver(To.substring(To.indexOf("<") + 1,To.indexOf(">")));
        else
            email.setReceiver(To);

        if (To.contains("=")){
            if(isBase64(To.substring(To.indexOf("="),To.lastIndexOf("=") + 1)))
                email.setReceiverNickname(FileUtilImpl.decodeText(To.substring(To.indexOf("="),To.lastIndexOf("=") + 1)));
        }else {
            email.setReceiverNickname(To);
        }



        email.setEmailID(headers.get("X-QQ-mid"));

        email.setSendTime(headers.get("Date"));


        String boundary = "";
        // 解码并处理消息体，从中提取附件和正文内容
        String attachmentFilename = "";
        byte[] attachmentData = null;
        String bodyContent = "";
        String currentPartContentType = "";
        String currentCodeType ="";
        String currentEncoding = "";
        byte[] htmlData = null;
        ArrayList<File> a = new ArrayList<>();
        email.setAttachment(a);
        StringBuilder attachmentName = new StringBuilder();



        if (headers.containsKey("boundary")){
            boundary = headers.get("boundary");

            for (String part : bodyStr.split(boundary)) {

                String[] lines = part.trim().split(FileUtilImpl.LINE_SEPARATOR);

                if (lines.length >= 2 && lines[0].startsWith("Content-Type: ")) {
                    if (lines[0].contains(";")){
                        currentPartContentType = lines[0].substring("Content-Type: ".length(),lines[0].indexOf(";")).trim();
                    }else {
                        currentPartContentType = lines[0].substring("Content-Type: ".length()).trim();
                    }

                    if (currentPartContentType.contains("multipart")){
                        partingDecode(part,email,headers.get("Message-ID"));
                        continue;
                    }
                    if (lines[0].contains("charset")){
                        if(lines[0].substring(lines[0].indexOf("charset")).contains(";")){
                            currentCodeType = lines[0].substring(lines[0].indexOf("=") + 1 , lines[0].indexOf(";" , lines[0].indexOf("charset"))).replaceAll("\"","").trim();
                        }else {
                            currentCodeType = lines[0].substring(lines[0].indexOf("=") + 1).replaceAll("\"","").trim();
                        }
                        currentEncoding = lines[1].substring(lines[1].indexOf(":") + 1).replaceAll("\"","").trim();
                    } else if(lines[1].contains("charset"))
                    {
                        if(lines[1].substring(lines[1].indexOf("charset")).contains(";")){
                            currentCodeType = lines[1].substring(lines[1].indexOf("=") + 1 , lines[1].indexOf(";" , lines[1].indexOf("charset"))).replaceAll("\"","").trim();
                        }else {
                            currentCodeType = lines[1].substring(lines[1].indexOf("=") + 1).replaceAll("\"","").trim();
                        }
                        currentEncoding = lines[2].substring(lines[2].indexOf(":") + 1).replaceAll("\"","").trim();
                    }
                    if (lines.length >= 4 && lines[3].contains("attachment")) {
                        if (lines[2].contains(".")){
                            attachmentFilename = lines[2].substring(lines[2].indexOf("\"")+1,lines[2].lastIndexOf("\""));
                        }else {
                            //String tmp = lines[2].substring(lines[2].indexOf("\"")+1,lines[2].lastIndexOf("\"")); // 获取附件文件名，并对其解码
                            attachmentFilename = FileUtilImpl.decodeText(lines[2].substring(lines[2].indexOf("\"")+1,lines[2].lastIndexOf("\""))); // 获取附件文件名，并对其解码
                        }
                        attachmentData = new byte[0];
                    }else if (lines.length >= 4 && lines[2].contains("attachment")){
                        if (lines[2].contains(".")){
                            attachmentFilename = lines[2].substring(lines[2].indexOf("\"")+1,lines[2].lastIndexOf("\""));
                        }else {
                            //String tmp = lines[2].substring(lines[2].indexOf("\"")+1,lines[2].lastIndexOf("\"")); // 获取附件文件名，并对其解码
                            attachmentFilename = FileUtilImpl.decodeText(lines[2].substring(lines[2].indexOf("\"")+1,lines[2].lastIndexOf("\""))); // 获取附件文件名，并对其解码
                        }
                        attachmentData = new byte[0];
                    }
                }
                if ("application/octet-stream".equals(currentPartContentType) && attachmentFilename != null) { // 处理附件部分
                    //String[]partlines = part.split("\r\n");

                    StringBuilder sb = new StringBuilder();
                    int index = 0;
                    while (!"".equals(lines[index])){
                        index+=1;
                    }
                    if("".equals(lines[index])){
                        index+=1;
                    }
                    while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                        sb.append(lines[index].trim());
                        index+=1;
                    }

                    byte[] decodedData = Base64.getDecoder().decode(sb.toString().getBytes());//不应该是整个part

                    attachmentData = Arrays.copyOf(attachmentData, attachmentData.length + decodedData.length); // 扩展数组
                    System.arraycopy(decodedData, 0, attachmentData, attachmentData.length - decodedData.length, decodedData.length); // 复制数据
                    currentPartContentType = "";

                    String path = "receiveAttachment\\";
                    if (email.getReceiver().contains("@")){
                        path += email.getReceiver().substring(0,email.getReceiver().indexOf("@"));
                        path += "\\";
                    }else {
                        path += email.getReceiver();
                        path += "\\";
                    }
                    File directory = new File(path);
                    if (!directory.exists()) {
                        directory.mkdirs();
                    }

                    path+=attachmentFilename;
                    File attachment = new File(path);
                    try (FileOutputStream fos = new FileOutputStream(attachment)) {
                        fos.write(attachmentData);
                    } catch (IOException e) {
                        System.out.println("An error occurred while writing the byte array to file: " + e.getMessage());
                    }

                    email.getAttachment().add(attachment);


                    if(attachmentName.length()>0){
                        attachmentName.append("?").append(attachmentFilename);
                    }else{
                        attachmentName.append(attachmentFilename);
                    }
                }
                if ("text/plain".equals(currentPartContentType)) { // 处理正文部分
                    //String[]partlines = part.split("\r\n");
                    StringBuilder sb = new StringBuilder();
                    int index = 0;
                    while (!"".equals(lines[index])){
                        index+=1;
                    }
                    if("".equals(lines[index])){
                        index+=1;
                    }


                    if (currentEncoding.startsWith("b") || currentEncoding.startsWith("B")){

                        while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                            sb.append(lines[index].trim());
                            index+=1;
                        }
                        bodyContent = new String(Base64.getMimeDecoder().decode(sb.toString().getBytes()),currentCodeType);

                    } else if (currentEncoding.startsWith("q") || currentEncoding.startsWith("Q")) {

                        while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                            sb.append(lines[index].trim());
                            index+=1;
                        }
                        QuotedPrintableCodec codec = new QuotedPrintableCodec();
                        try {
                            bodyContent = codec.decode(sb.toString(),currentCodeType);
                        } catch (Exception e) {
                            bodyContent = sb.toString();
                        }

                    } else if (currentEncoding.startsWith("7")) {
                        while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                            sb.append(lines[index].trim()).append("\n");
                            index+=1;
                        }
                        bodyContent = sb.toString();
                    } else if (currentEncoding.startsWith("8")) {
                        while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                            sb.append(lines[index].trim());
                            index+=1;
                        }
                        bodyContent = new String(sb.toString().getBytes(),currentCodeType);
                    }else{
                        while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                            sb.append(lines[index].trim());
                            index+=1;
                        }
                        bodyContent = sb.toString();
                    }


                    email.setContent(bodyContent);
                    currentPartContentType = "";
                }
                if (currentPartContentType.contains("text/html")) { // 处理html部分
                    //String[]partlines = part.split("\r\n");
                    htmlData = new byte[0];
                    StringBuilder sb = new StringBuilder();
                    int index = 0;
                    while (!"".equals(lines[index].trim()))
                        index+=1;

                    if("".equals(lines[index])){
                        index+=1;
                    }
                    byte[] decodedData = null;

                    //以下设置HTML文件

                    if ("base64".equals(currentEncoding)){

                        while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                            sb.append(lines[index].trim());
                            index+=1;
                        }
                        decodedData = Base64.getDecoder().decode(sb.toString().getBytes());
                        htmlData = Arrays.copyOf(htmlData, htmlData.length + decodedData.length); // 扩展数组
                        System.arraycopy(decodedData, 0, htmlData, htmlData.length - decodedData.length, decodedData.length); // 复制数据

//                        if (email.getContent()==null){
                        email.setContent(sb.toString());
//                        }
                        email.setHtmlString(sb.toString());
                    }
                    else if ("QUOTED-PRINTABLE".equals(currentEncoding)||"quoted-printable".equals(currentEncoding)){
                        while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                            sb.append(lines[index].trim());
                            index+=1;
                        }
                        email.setHtmlString(sb.toString());
//                        if (email.getContent()==null){
                        email.setContent(sb.toString());
//                        }
                    }



                    currentPartContentType = "";
                }

            }


        }else {

            currentPartContentType = headers.get("Content-Type");
            bodyStr = bodyStr.substring(bodyStr.indexOf("}") + 1 , bodyStr.lastIndexOf(")")).replaceAll("\r","");
            String[] lines = bodyStr.trim().split("\n");
            int index = 0;

            while ("".equals(lines[index])){
                index+=1;
            }

            currentEncoding = headers.get("Content-Transfer-Encoding");
            StringBuilder sb = new StringBuilder();
            if ("base64".equals(currentEncoding) || "Base64".equals(currentEncoding)){
                bodyStr = bodyStr.replaceAll("(\r\n)*|\n*|\r*","");

                while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                    sb.append(lines[index].trim());
                    index+=1;
                }
                bodyContent = new String(Base64.getMimeDecoder().decode(sb.toString().getBytes()),headers.get("charset"));

            }else if ("7bit".equals(currentEncoding)){
                while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                    sb.append(lines[index].trim()).append("\n");
                    index+=1;
                }
                //遇到的7bit 好像都解码好了 所以直接拿
                bodyContent = sb.toString();
            }else if ("8bit".equals(currentEncoding)){
//                String line = lines[index];
//                while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
//                    sb.append(lines[index].trim()).append("\n");
//                    index+=1;
//                }
                bodyContent = new String(bodyStr.getBytes(),headers.get("charset"));
            }else if ("quoted-printable".equals(currentEncoding) || "QUOTED-PRINTABLE".equals(currentEncoding)){
                while (index<lines.length&&!"".equals(lines[index].trim())&&!"--".equals(lines[index].trim())){
                    sb.append(lines[index].trim()).append("\n");
                    index+=1;
                }
                QuotedPrintableCodec codec = new QuotedPrintableCodec();
                try {
                    bodyContent = codec.decode(sb.toString(),headers.get("charset"));
                } catch (Exception e) {
                    bodyContent = bodyStr;
                }
            }
            email.setContent(bodyContent);
        }
        email.setAttachmentName(attachmentName.toString());
        return email;
    }

    /**
     * 读取文件并返回二进制内容
     * 用于读取附件返回二进制数组以进行传输
     */
    private static byte[] getAttachmentData(File attachment) throws IOException {

        // 文件大小
        long length = attachment.length();

        // 用于返回的字节数组
        byte[] data = new byte[(int)length];

        // 将文件中的内容读取至字节数组
        FileInputStream fis = new FileInputStream(attachment);
        int offset = 0;
        int numRead = 0;

        while (offset < data.length && (numRead = fis.read(data, offset, data.length-offset)) >= 0) {
            offset += numRead;
        }

        fis.close();

        if (offset < data.length) {
            throw new IOException("Could not completely read file "+attachment.getName());
        }

        return data;
    }

    private static String encodeText(String text) throws UnsupportedEncodingException {

        return Base64.getEncoder().encodeToString(text.getBytes("utf-8"));
        //"=?utf-8?B?" +  + "?="
    }

    public static String decodeText(String text) throws  UnsupportedEncodingException {
        String decodeType = "utf-8";
        String encoding = "B";
        String extend = "";
        if (text.contains("=?")){
            decodeType = text.substring(text.indexOf("?") + 1, text.indexOf("?" , text.indexOf("?") + 1));
            encoding = text.substring(text.indexOf(decodeType) + decodeType.length() + 1);
            extend = text.substring(text.lastIndexOf("=") + 1);
            text = text.substring(0,text.lastIndexOf("=") + 1).replaceAll("=\\?.*\\?(B|b|Q|q)\\?", "").replaceAll("\\?=", "");
        }

        String re = text;
        if (encoding.startsWith("B") || encoding.startsWith("b")){
            try {
                re = new String(Base64.getMimeDecoder().decode(text),decodeType);
            }catch (Exception e){
                return text;
            }
        } else if (encoding.startsWith("Q") || encoding.startsWith("q")){
            QuotedPrintableCodec codec = new QuotedPrintableCodec();
            try {
                re = codec.decode(text,decodeType);
            } catch (Exception e) {
                return text;
            }
        }

        return re + extend;
    }


    public static boolean isBase64(String text){
        /*try {
            text = text.trim().replaceAll("=\\?.*\\?(B|b|Q|q)\\?", "").replaceAll("\\?=", "");
            byte[] decoded = Base64.getDecoder().decode(text);
            return Arrays.equals(decoded, Base64.getEncoder().encodeToString(decoded).getBytes());
        } catch (IllegalArgumentException e) {
            return false;
        }*/
        //上述算法无用  遂采用
        //大道至简算法
        return text.startsWith("=?");
    }

    /**
     * 将Email对象封装为JSON文件
     */
    private static File getJSON(Email email) throws IOException {
        String uuidStr = UUID.randomUUID().toString();
        File json = new File(uuidStr+".json");

        ObjectMapper mapper = new ObjectMapper();

        mapper.writeValue(json,email);

        return json;
    }

}
